package com.maxd.controller.cash;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayFundTransToaccountTransferRequest;
import com.alipay.api.request.AlipayFundTransUniTransferRequest;
import com.alipay.api.response.AlipayFundTransToaccountTransferResponse;
import com.alipay.api.response.AlipayFundTransUniTransferResponse;
import com.google.common.base.Charsets;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.maxd.adapter.IgnoreSecurity;
import com.maxd.constants.AliPayConstants;
import com.maxd.error.ExceptionEnum;
import com.maxd.error.Result;
import com.maxd.error.ResultUtil;
import com.maxd.model.*;
import com.maxd.respository.cash.CashJpaRepository;
import com.maxd.respository.cash.CashRepository;
import com.maxd.respository.common.CommonRepository;
import com.maxd.respository.order.OrderRepository;
import com.maxd.respository.userinfo.UserJpaRepository;
import com.maxd.respository.userinfo.UserRepository;
import com.maxd.service.cash.ICashService;
import com.maxd.service.message.IMessageService;
import com.maxd.service.money.IMoneyDetailsService;
import com.maxd.service.pay.PayDetailsService;
import com.maxd.service.userMoney.UserMoneyService;
import com.maxd.service.userinfo.UserServiceImpl;
import com.maxd.service.wx.AccountService;
import com.maxd.utils.AmountCalUtils;
import com.maxd.utils.Config;
import com.maxd.utils.HttpClient;
import com.maxd.utils.HttpClientUtil;
import com.maxd.utils.wx.*;
import com.yungouos.pay.util.PaySignUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.val;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.*;
import weixin.popular.bean.message.templatemessage.TemplateMessageItem;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.locks.ReentrantReadWriteLock;

@RestController
@Api(value = "用户结算管理", tags = {"用户结算管理"})
@RequestMapping(value = "/cash")
public class CashController {
    private Logger logger = LoggerFactory.getLogger(CashController.class);
    @Autowired
    private OrderRepository orderRepository;
    @Autowired
    private ICashService iCashService;
    @Autowired
    private UserJpaRepository userJpaRepository;
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private CashJpaRepository cashJpaRepository;
    @Autowired
    private CashRepository cashRepository;
    @Autowired
    private CommonRepository commonRepository;
    @Autowired
    private AccountService accountService;
    @Autowired
    private UserServiceImpl userService;
    @Autowired
    private IMessageService iMessageService;
    @Autowired
    private IMoneyDetailsService iMoneyDetailsService;
    @Autowired
    private PayDetailsService payDetailsService;
    @Autowired
    private UserMoneyService userMoneyService;
    private ReentrantReadWriteLock reentrantReadWriteLock=new ReentrantReadWriteLock(true);

    private ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().build();
    private ExecutorService singleThreadPool = new ThreadPoolExecutor(30, 100,
            0L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());


    @RequestMapping(value = "/sendMsg", method = RequestMethod.GET)
    @ApiOperation("管理平台主动推送消息")
    @ResponseBody
    public Result sendMsg(String title,String content,String phone,Integer flag){
        if(flag==1){
            //根据手机号推送
            UserInfo userByPhone = userRepository.getUserByPhone(phone);
            if(null==userByPhone){
                return ResultUtil.error(-100,"手机号不存在！");
            }
            send(userByPhone,title,content);
        }else{
            //所有人推送
            List<UserInfo> userInfos = userRepository.selectUserList();
            //用户数量较大  使用多线程推送  根据用户数量进行拆分  同时按照3个线程进行推送
            int count = userInfos.size() / 3;
            singleThreadPool.submit(() -> {
                for(int i=0 ;i<count;i++){
                    send(userInfos.get(i),title,content);
                }
            });
            singleThreadPool.submit(() -> {
                for(int i=count ;i<count*2;i++){
                    send(userInfos.get(i),title,content);
                }
            });
            singleThreadPool.submit(() -> {
                for(int i=count*2 ;i<userInfos.size();i++){
                    send(userInfos.get(i),title,content);
                }
            });
           /* for(UserInfo userByPhone:userInfos){

            }*/
        }
        return ResultUtil.success();
    }


    private void send(UserInfo userByPhone,String title,String content){
        if (userByPhone.getClientid() != null) {
            userService.pushToSingle(title, content, userByPhone.getClientid());
        }
        MessageInfo messageInfo = new MessageInfo();
        messageInfo.setContent(content);
        messageInfo.setTitle(title);
        messageInfo.setState(String.valueOf(8));
        messageInfo.setUserName(userByPhone.getNickName());
        messageInfo.setUserId(String.valueOf(userByPhone.getId()));
        iMessageService.saveBody(messageInfo);
    }

    /**
     * 查询充值记录
     *
     * @return
     */
    @RequestMapping(value = "/selectPayDetails", method = RequestMethod.POST)
    @ApiOperation("查询充值记录")
    @ResponseBody
    public Result selectPayDetails(int page,int size,String phone,String startTime,String endTime) {
        Sort.Order order = new Sort.Order(Sort.Direction.DESC, "id");
        Pageable pageable = PageRequest.of(page, size, Sort.by(order));
        return ResultUtil.success(payDetailsService.selectPayDetails(pageable,phone,startTime,endTime));
    }

    @RequestMapping(value = "/selectPayDetailsByUserId", method = RequestMethod.POST)
    @ApiOperation("查询充值记录")
    @ResponseBody
    public Result selectPayDetailsByUserId(int page,int size,Long userId,String startTime,String endTime) {
        Sort.Order order = new Sort.Order(Sort.Direction.DESC, "id");
        Pageable pageable = PageRequest.of(page, size, Sort.by(order));
        return ResultUtil.success(payDetailsService.selectPayDetailsByUserId(pageable,userId,startTime,endTime));
    }



    /**
     * 管理平台查询某个用户的提现记录
     *
     * @return
     */
    @RequestMapping(value = "/phone/{phone}", method = RequestMethod.GET)
    @ApiOperation("管理平台查询某个用户的提现记录")
    @ResponseBody
    public Result findByPhone(@PathVariable String phone) {
        return iCashService.findByPhone(phone);
    }

    /**
     * 管理平台查询用户提现列表
     *
     * @param page
     * @param size
     * @return
     */
    @RequestMapping(value = "/page/{page}/{size}", method = RequestMethod.GET)
    @ApiOperation("管理平台查询用户提现列表")
    @ResponseBody
    public Result getList(@PathVariable int page, @PathVariable int size) {
        Sort.Order order = new Sort.Order(Sort.Direction.DESC, "id");
        Pageable pageable = PageRequest.of(page, size, Sort.by(order));
        return ResultUtil.success(cashJpaRepository.findAll(pageable));
    }


    @RequestMapping(value = "/selectCashList", method = RequestMethod.GET)
    @ApiOperation("管理平台查询用户提现列表")
    @ResponseBody
    public Result getList(Integer page,Integer size,String zhifubao,String relationId,Integer state) {
        Sort.Order order = new Sort.Order(Sort.Direction.DESC, "id");
        Pageable pageable = PageRequest.of(page, size, Sort.by(order));
        //构造自定义查询条件
        Specification<CashOut> queryCondition = new Specification<CashOut>() {
            @Override
            public Predicate toPredicate(Root<CashOut> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicateList = new ArrayList<>();
                if (StringUtils.isNotEmpty(zhifubao)) {
                    predicateList.add(criteriaBuilder.like(root.get("zhifubao"), zhifubao));
                }
                if (StringUtils.isNotEmpty(relationId)) {
                    predicateList.add(criteriaBuilder.equal(root.get("relationId"), relationId));
                }
                if (state != 2) {
                    predicateList.add(criteriaBuilder.equal(root.get("state"), state));
                }
                return criteriaBuilder.and(predicateList.toArray(new Predicate[predicateList.size()]));
            }
        };
        return ResultUtil.success(cashJpaRepository.findAll(queryCondition, pageable));
    }


    @RequestMapping(value = "/update", method = RequestMethod.POST)
    @ApiOperation("管理平台修改用户提现状态")
    @ResponseBody
    public Result updateIsOut(@RequestParam Boolean isOut, @RequestParam Long id) {
        return iCashService.updateIsOut(isOut, id);
    }


    /**
     * 管理平台计算用户可提现金额
     *
     * @return
     */
    @RequestMapping(value = "/userToTalMoney", method = RequestMethod.POST)
    @ApiOperation("管理平台计算用户可提现金额")
    @ResponseBody
    @IgnoreSecurity
    public Result userToTalMoney() {
        return iCashService.userToTalMoney();
    }

    /**
     * 管理平台计算用户可提现金额
     *
     * @return
     */
    @RequestMapping(value = "/userToTalMoneys", method = RequestMethod.GET)
    @ApiOperation("管理平台计算用户可提现金额")
    @ResponseBody
    @IgnoreSecurity
    public Result userToTalMoneys(Integer month) {
        return iCashService.userToTalMoneys(month);
    }

    @RequestMapping(value = "/validateUserMoney/{id}", method = RequestMethod.GET)
    @ApiOperation("管理平台验证用户的提现金额")
    @ResponseBody
    public Result validateUserMoney(@PathVariable String id) {
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM");
        Calendar cal1 = Calendar.getInstance();
        //获取上个月的日期（上个月的今天）
        cal1.setTime(new Date());
        cal1.add(Calendar.MONTH, -1);
        Date date3 = cal1.getTime();
        String s = orderRepository.countByTime(sdf1.format(date3), Long.valueOf(id), 1);
        return ResultUtil.success(s);
    }

    /**
     * 管理平台确认提现
     *
     * @param cashId
     * @return
     */
    @RequestMapping(value = "/update/{cashId}", method = RequestMethod.POST)
    @ApiOperation("管理平台确认提现")
    @ResponseBody
    public Result update(@PathVariable Long cashId) {
        CashOut one1 = cashJpaRepository.findById(cashId).orElse(null);
        CommonInfo url = commonRepository.findOne(19);
        CashOut one = cashJpaRepository.findById(cashId).orElse(null);
        if (one == null) {
            return ResultUtil.error(ExceptionEnum.USER_NOT_FIND);
        }
        assert one1 != null;
        if (one1.getOut()) {
            return ResultUtil.error(9999, one1.getZhifubaoName() + "转账失败！原因是用户已转账");
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date now = new Date();
        one.setOut(true);
        one.setOutAt(sdf.format(now));
        CashOut save = cashJpaRepository.save(one);
        String userId = save.getUserId();
        UserInfo userInfo = userJpaRepository.getOne(Long.valueOf(userId));
        if (userInfo != null && userInfo.getOpenId() != null) {
            //推送提现通知消息
            cashOutSuccess(userInfo.getOpenId(), save.getOutAt(), save.getMoney(), save.getZhifubao(), url.getValue());
        }
        return ResultUtil.success(one1.getZhifubaoName() + "转账成功");
    }


    @RequestMapping(value = "/alipay/{cashId}", method = RequestMethod.POST)
    @ApiOperation("管理平台确认提现")
    @ResponseBody
    public Result alipayPay(@PathVariable Long cashId) {
        /**
         * 初始化客户端
         */
       AlipayClient alipayClient = new DefaultAlipayClient(AliPayConstants.REQUEST_URL,
               commonRepository.findOne(63).getValue(), commonRepository.findOne(65).getValue(), AliPayConstants.FORMAT,
                AliPayConstants.CHARSET, commonRepository.findOne(64).getValue(), AliPayConstants.SIGNTYPE);
        CashOut one1 = cashJpaRepository.findById(cashId).orElse(null);
        //获取全局名称
        //是否开启企业支付
        CommonInfo commonInfo = commonRepository.findOne(51);
        CashOut one = cashJpaRepository.findById(cashId).orElse(null);
        if (one == null) {
            return ResultUtil.error(ExceptionEnum.USER_NOT_FIND);
        }
        assert one1 != null;
        if (one1.getOut()) {
            return ResultUtil.error(9999, one1.getZhifubaoName() + "转账失败！原因是用户已转账");
        }
        DecimalFormat df= new DecimalFormat("#.00");
        Double money=Double.parseDouble(one.getMoney());
        one.setMoney(df.format(money));

        if (commonInfo.getValue() != null && commonInfo.getValue().equals("是")) {
            val aliPayWithdrawModel = AliPayWithdrawModel.builder()
                    .out_biz_no(one.getOrderNumber())
                    .amount(new BigDecimal(one.getMoney()))
                    .payee_account(one.getZhifubao())
                    .payee_real_name(one.getZhifubaoName())
                    .payee_type(AliPayConstants.PAY_TYPE)
                    .remark(commonRepository.findOne(12).getValue() + "佣金结算")
                    .build();
            String json = JSON.toJSONString(aliPayWithdrawModel);
            //实例化连接对象
            AlipayFundTransToaccountTransferRequest withdrawRequest = new AlipayFundTransToaccountTransferRequest();
            withdrawRequest.setBizContent(json);
            try {
                AlipayFundTransToaccountTransferResponse response = alipayClient.execute(withdrawRequest);
                if (AliPayConstants.SUCCESS_CODE.equalsIgnoreCase(response.getCode())) {
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    one.setOut(true);
                    one.setOutAt(sdf.format(new Date()));
                    CashOut save = cashJpaRepository.save(one);
                    UserInfo userInfo = userJpaRepository.getOne(Long.valueOf(save.getUserId()));
                    if (userInfo != null && userInfo.getOpenId() != null) {
                        //提现通知消息
                        cashOutSuccess(userInfo.getOpenId(), save.getOutAt(), save.getMoney(), save.getZhifubao(), commonRepository.findOne(19).getValue());
                    }
                    return ResultUtil.success(one1.getZhifubaoName() + "转账成功");
                } else {
                    return ResultUtil.error(9999, one1.getZhifubaoName() + "转账失败！" + response.getSubMsg());
                }
            } catch (AlipayApiException e) {
                logger.error("零钱提现异常原因:" + e.getMessage());
                e.printStackTrace();
                return ResultUtil.error(9999, one1.getZhifubaoName() + "转账失败！" + e.getMessage());

            }
        } else {
            //人工转账后改变状态的
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date now = new Date();
            one.setOut(true);
            one.setOutAt(sdf.format(now));
            CashOut save = cashJpaRepository.save(one);
            String userId = save.getUserId();
            UserInfo userInfo = userJpaRepository.getOne(Long.valueOf(userId));
            if (userInfo != null && userInfo.getOpenId() != null) {
                //推送提现通知消息
                cashOutSuccess(userInfo.getOpenId(), save.getOutAt(), save.getMoney(), save.getZhifubao(), commonRepository.findOne(19).getValue());
            }
            return ResultUtil.success(one1.getZhifubaoName() + "转账成功");
        }
    }

    @RequestMapping(value = "/v1/alipay/{cashId}", method = RequestMethod.POST)
    @ApiOperation("管理平台确认提现")
    @ResponseBody
    public Result v1alipayPay(@PathVariable Long cashId) {
        reentrantReadWriteLock.writeLock().lock();
        try {
            //获取全局名称
            //是否开启企业支付
            CommonInfo commonInfo = commonRepository.findOne(87);
            CashOut one = cashJpaRepository.findById(cashId).orElse(null);
            if (one == null) {
                return ResultUtil.error(ExceptionEnum.USER_NOT_FIND);
            }
            assert one != null;
            if (one.getState()!=0) {
                return ResultUtil.error(9999, one.getZhifubaoName() + "转账失败！原因是用户已转账");
            }
            if(StringUtils.isEmpty(one.getOrderNumber())){
                one.setOrderNumber(String.valueOf(System.currentTimeMillis()));
            }
            DecimalFormat df= new DecimalFormat("#.00");
            Double money=Double.parseDouble(one.getMoney());
            one.setMoney(df.format(money));
            if (commonInfo.getValue() != null && commonInfo.getValue().equals("1")) {
                val aliPayWithdrawModel = AliPayWithdrawModel.builder()
                        .out_biz_no(one.getOrderNumber())
                        .amount(new BigDecimal(one.getMoney()))
                        .payee_account(one.getZhifubao())
                        .payee_real_name(one.getZhifubaoName())
                        .payee_type(AliPayConstants.PAY_TYPE)
                        .remark(commonRepository.findOne(12).getValue() + "佣金结算")
                        .build();
                String json = JSON.toJSONString(aliPayWithdrawModel);
                //实例化连接对象
                AlipayFundTransToaccountTransferRequest withdrawRequest = new AlipayFundTransToaccountTransferRequest();
                withdrawRequest.setBizContent(json);
                AlipayClient alipayClient = new DefaultAlipayClient(AliPayConstants.REQUEST_URL,
                        commonRepository.findOne(63).getValue(), commonRepository.findOne(65).getValue(), AliPayConstants.FORMAT,
                        AliPayConstants.CHARSET, commonRepository.findOne(64).getValue(), AliPayConstants.SIGNTYPE);
                try {
                    AlipayFundTransToaccountTransferResponse response = alipayClient.execute(withdrawRequest);
                    if (AliPayConstants.SUCCESS_CODE.equalsIgnoreCase(response.getCode())) {
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        one.setState(1);
                        one.setOut(true);
                        one.setOutAt(sdf.format(new Date()));
                        CashOut save = cashJpaRepository.save(one);
                        UserInfo userInfo = userJpaRepository.getOne(Long.valueOf(save.getUserId()));
                        if (userInfo != null && userInfo.getOpenId() != null) {
                            //提现通知消息
                            cashOutSuccess(userInfo.getOpenId(), save.getOutAt(), save.getMoney(), save.getZhifubao(), commonRepository.findOne(19).getValue());
                        }
                        return ResultUtil.success(one.getZhifubaoName() + "转账成功");
                    } else {
                        return ResultUtil.error(9999, one.getZhifubaoName() + "转账失败！" + response.getSubMsg());
                    }
                } catch (AlipayApiException e) {
                    logger.error("零钱提现异常原因:" + e.getMessage());
                    e.printStackTrace();
                    return ResultUtil.error(9999, one.getZhifubaoName() + "转账失败！" + e.getMessage());

                }
            }else if(commonInfo.getValue() != null && commonInfo.getValue().equals("2")){
                String url="https://api.pay.yungouos.com/api/finance/repay/alipay";
                Map<String,String> map=new HashMap<>();
                CommonInfo merchantId = commonRepository.findOne(235);
                CommonInfo password = commonRepository.findOne(236);
                map.put("merchant_id",merchantId.getValue());//YunGouOS商户ID。登录YunGouOS.com-》账户设置-》开发者身份-》账户商户号；
                map.put("out_trade_no",one.getOrderNumber());
                map.put("account",one.getZhifubao());
                map.put("account_name",one.getZhifubaoName());
                map.put("money",one.getMoney());
                map.put("desc",commonRepository.findOne(12).getValue() + "佣金结算");
                Map<String,Object> maps=new HashMap<>();
                maps.put("merchant_id",merchantId.getValue());
                maps.put("out_trade_no",one.getOrderNumber());
                maps.put("account",one.getZhifubao());
                maps.put("account_name",one.getZhifubaoName());
                maps.put("money",one.getMoney());
                maps.put("desc",commonRepository.findOne(12).getValue() + "佣金结算");
                map.put("sign", PaySignUtil.createSign(maps,password.getValue()));
                String s = HttpClientUtil.doPost(url, map);
                JSONObject jsonObject = JSON.parseObject(s);
                String code = jsonObject.getString("code");
                if("1".equals(code)){
                    JSONObject data = jsonObject.getJSONObject("data");
                    String status = data.getString("status");
                    if("1".equals(status)){
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        one.setState(1);
                        one.setOutAt(sdf.format(new Date()));
                        CashOut save = cashJpaRepository.save(one);
                        return ResultUtil.success(one.getZhifubaoName() + "转账成功");
                    }else{
                        return ResultUtil.error(9999,"转账失败，原因："+data.getString("reason"));
                    }
                }else{
                    logger.error("yungouos:"+s);
                    return ResultUtil.error(9999,"转账失败，参数配置有误！");
                }
            }else if (commonInfo.getValue() != null && commonInfo.getValue().equals("3")) {
                try {
                    CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
                    certAlipayRequest.setServerUrl("https://openapi.alipay.com/gateway.do");  //gateway:支付宝网关（固定）https://openapi.alipay.com/gateway.do
                    certAlipayRequest.setAppId(commonRepository.findOne(170).getValue());  //APPID 即创建应用后生成,详情见创建应用并获取 APPID
                    certAlipayRequest.setPrivateKey(commonRepository.findOne(171).getValue());  //开发者应用私钥，由开发者自己生成
                    certAlipayRequest.setFormat("json");  //参数返回格式，只支持 json 格式
                    certAlipayRequest.setCharset(AliPayConstants.CHARSET);  //请求和签名使用的字符编码格式，支持 GBK和 UTF-8
                    certAlipayRequest.setSignType(AliPayConstants.SIGNTYPE);  //商户生成签名字符串所使用的签名算法类型，目前支持 RSA2 和 RSA，推荐商家使用 RSA2。

                    CommonInfo url = commonRepository.findOne(200);
                    certAlipayRequest.setCertPath(url.getValue()+"/appCertPublicKey.crt"); //应用公钥证书路径（app_cert_path 文件绝对路径）
                    certAlipayRequest.setAlipayPublicCertPath(url.getValue()+"/alipayCertPublicKey_RSA2.crt"); //支付宝公钥证书文件路径（alipay_cert_path 文件绝对路径）
                    certAlipayRequest.setRootCertPath(url.getValue()+"/alipayRootCert.crt");  //支付宝CA根证书文件路径（alipay_root_cert_path 文件绝对路径）
                    AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
                    AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
                    request.setBizContent("{" +
                            "\"out_biz_no\":\""+one.getOrderNumber()+"\"," +
                            "\"trans_amount\":"+new BigDecimal(one.getMoney())+"," +
                            "\"product_code\":\"TRANS_ACCOUNT_NO_PWD\"," +
                            "\"biz_scene\":\"DIRECT_TRANSFER\"," +
                            "\"order_title\":\""+commonRepository.findOne(12).getValue() + "佣金结算"+"\"," +
                            "\"payee_info\":{" +
                            "\"identity\":\""+one.getZhifubao()+"\"," +
                            "\"identity_type\":\"ALIPAY_LOGON_ID\"," +
                            "\"name\":\""+one.getZhifubaoName()+"\"," +
                            "}," +
                            "\"remark\":\""+commonRepository.findOne(12).getValue() + "佣金结算"+"\"" +
                            "}");
                    AlipayFundTransUniTransferResponse response = null;
                    response = alipayClient.certificateExecute(request);
                    if(response.isSuccess()){
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        one.setState(1);
                        one.setOut(true);
                        one.setOutAt(sdf.format(new Date()));
                        CashOut save = cashJpaRepository.save(one);
                        UserInfo userInfo = userJpaRepository.findById(Long.valueOf(save.getUserId())).orElse(null);
                        if (userInfo != null && userInfo.getOpenId() != null) {
                            //提现通知消息
                            cashOutSuccess(userInfo.getOpenId(), save.getOutAt(), save.getMoney(), save.getZhifubao(), commonRepository.findOne(19).getValue());
                        }
                        return ResultUtil.success(one.getZhifubaoName() + "转账成功");
                    } else {
                        return ResultUtil.error(9999, one.getZhifubaoName() + "转账失败！" + response.getSubMsg());
                    }
                } catch (AlipayApiException e) {
                    logger.error("零钱提现异常原因:" + e.getMessage());
                    e.printStackTrace();
                    return ResultUtil.error(9999, one.getZhifubaoName() + "转账失败！" + e.getMessage());
                }
            } else {
                //人工转账后改变状态的
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date now = new Date();
                one.setState(1);
                one.setOut(true);
                one.setOutAt(sdf.format(now));
                CashOut save = cashJpaRepository.save(one);
                String userId = save.getUserId();
                UserInfo userInfo = userJpaRepository.getOne(Long.valueOf(userId));
                if (userInfo != null && userInfo.getOpenId() != null) {
                    //推送提现通知消息
                    cashOutSuccess(userInfo.getOpenId(), save.getOutAt(), save.getMoney(), save.getZhifubao(), commonRepository.findOne(19).getValue());
                }
                return ResultUtil.success(one.getZhifubaoName() + "转账成功");
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.error("转账异常："+e.getMessage());
        }finally {
            reentrantReadWriteLock.writeLock().unlock();
        }
        return ResultUtil.error(-200,"系统繁忙，请稍后再试！");
    }



    @RequestMapping(value = "/v2/alipay/{cashId}", method = RequestMethod.POST)
    @ApiOperation("管理平台确认提现")
    @ResponseBody
    public Result v2alipayPay(@PathVariable Long cashId) {

        //获取全局名称
        //是否开启企业支付
        CommonInfo commonInfo = commonRepository.findOne(87);
        CashOut one = cashJpaRepository.findById(cashId).orElse(null);
        if (one == null) {
            return ResultUtil.error(ExceptionEnum.USER_NOT_FIND);
        }
        assert one != null;
        if (one.getState()!=0) {
            return ResultUtil.error(9999, one.getZhifubaoName() + "转账失败！原因是用户已转账");
        }
        DecimalFormat df= new DecimalFormat("#.00");
        Double money=Double.parseDouble(one.getMoney());
        one.setMoney(df.format(money));
        if (commonInfo.getValue() != null && commonInfo.getValue().equals("1")) {
            try {
                CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
                certAlipayRequest.setServerUrl("https://openapi.alipay.com/gateway.do");  //gateway:支付宝网关（固定）https://openapi.alipay.com/gateway.do
                certAlipayRequest.setAppId(commonRepository.findOne(170).getValue());  //APPID 即创建应用后生成,详情见创建应用并获取 APPID
                certAlipayRequest.setPrivateKey(commonRepository.findOne(171).getValue());  //开发者应用私钥，由开发者自己生成
                certAlipayRequest.setFormat("json");  //参数返回格式，只支持 json 格式
                certAlipayRequest.setCharset(AliPayConstants.CHARSET);  //请求和签名使用的字符编码格式，支持 GBK和 UTF-8
                certAlipayRequest.setSignType(AliPayConstants.SIGNTYPE);  //商户生成签名字符串所使用的签名算法类型，目前支持 RSA2 和 RSA，推荐商家使用 RSA2。

                CommonInfo url = commonRepository.findOne(200);
                certAlipayRequest.setCertPath(url.getValue()+"/appCertPublicKey.crt"); //应用公钥证书路径（app_cert_path 文件绝对路径）
                certAlipayRequest.setAlipayPublicCertPath(url.getValue()+"/alipayCertPublicKey_RSA2.crt"); //支付宝公钥证书文件路径（alipay_cert_path 文件绝对路径）
                certAlipayRequest.setRootCertPath(url.getValue()+"/alipayRootCert.crt");  //支付宝CA根证书文件路径（alipay_root_cert_path 文件绝对路径）
                AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
                AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
                request.setBizContent("{" +
                        "\"out_biz_no\":\""+one.getOrderNumber()+"\"," +
                        "\"trans_amount\":"+new BigDecimal(one.getMoney())+"," +
                        "\"product_code\":\"TRANS_ACCOUNT_NO_PWD\"," +
                        "\"biz_scene\":\"DIRECT_TRANSFER\"," +
                        "\"order_title\":\""+commonRepository.findOne(12).getValue() + "佣金结算"+"\"," +
                        "\"payee_info\":{" +
                        "\"identity\":\""+one.getZhifubao()+"\"," +
                        "\"identity_type\":\"ALIPAY_LOGON_ID\"," +
                        "\"name\":\""+one.getZhifubaoName()+"\"," +
                        "}," +
                        "\"remark\":\""+commonRepository.findOne(12).getValue() + "佣金结算"+"\"" +
                        "}");
                AlipayFundTransUniTransferResponse response = null;
                response = alipayClient.certificateExecute(request);
                logger.error("支付宝转账返回值："+response.getBody());
                if(response.isSuccess()){
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    one.setState(1);
                    one.setOut(true);
                    one.setOutAt(sdf.format(new Date()));
                    CashOut save = cashJpaRepository.save(one);
                    UserInfo userInfo = userJpaRepository.findById(Long.valueOf(save.getUserId())).orElse(null);
                    if (userInfo != null && userInfo.getOpenId() != null) {
                        //提现通知消息
                        cashOutSuccess(userInfo.getOpenId(), save.getOutAt(), save.getMoney(), save.getZhifubao(), commonRepository.findOne(19).getValue());
                    }
                    return ResultUtil.success(one.getZhifubaoName() + "转账成功");
                } else {
                    return ResultUtil.error(9999, one.getZhifubaoName() + "转账失败！" + response.getSubMsg());
                }
            } catch (AlipayApiException e) {
                logger.error("零钱提现异常原因:" + e.getMessage());
                e.printStackTrace();
                return ResultUtil.error(9999, one.getZhifubaoName() + "转账失败！" + e.getMessage());
            }
        }else if(commonInfo.getValue() != null && commonInfo.getValue().equals("2")){
            CommonInfo one1 = commonRepository.findOne(88);
            if(one1==null || StringUtils.isBlank(one1.getValue())){
                return ResultUtil.error(9999,"请设置转账秘钥");
            }
            Map<String,String> map=new HashMap<>();
            Object o = JSONArray.toJSON(one);
            map.put("jsonCashOut",new String(o.toString().getBytes(), Charsets.UTF_8));
            map.put("secretKey",one1.getValue());
            String body = HttpClientUtil.doPost("https://money.xiansqx.com/sqx_fast/cash/alipay", map);
            JSONObject jsonObject = JSON.parseObject(body);
            Integer code = jsonObject.getInteger("code");
            if(code!=0){
                return ResultUtil.error(9999,jsonObject.getString("msg"));
            }else{
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                one.setState(1);
                one.setOut(true);
                one.setOutAt(sdf.format(new Date()));
                CashOut save = cashJpaRepository.save(one);
                UserInfo userInfo = userJpaRepository.getOne(Long.valueOf(save.getUserId()));
                if (userInfo != null && userInfo.getOpenId() != null) {
                    //提现通知消息
                    cashOutSuccess(userInfo.getOpenId(), save.getOutAt(), save.getMoney(), save.getZhifubao(), commonRepository.findOne(19).getValue());
                }
                return ResultUtil.success(one.getZhifubaoName() + "转账成功");
            }
        } else {
            //人工转账后改变状态的
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date now = new Date();
            one.setState(1);
            one.setOut(true);
            one.setOutAt(sdf.format(now));
            CashOut save = cashJpaRepository.save(one);
            String userId = save.getUserId();
            UserInfo userInfo = userJpaRepository.getOne(Long.valueOf(userId));
            if (userInfo != null && userInfo.getOpenId() != null) {
                //推送提现通知消息
                cashOutSuccess(userInfo.getOpenId(), save.getOutAt(), save.getMoney(), save.getZhifubao(), commonRepository.findOne(19).getValue());
            }
            return ResultUtil.success(one.getZhifubaoName() + "转账成功");
        }
    }


    @RequestMapping(value = "/v3/alipay/{cashId}", method = RequestMethod.POST)
    @ApiOperation("管理平台确认提现")
    @ResponseBody
    public Result v3alipayPay(@PathVariable Long cashId) {
        reentrantReadWriteLock.writeLock().lock();
        try{
            CashOut one = cashJpaRepository.findById(cashId).orElse(null);
            if (one == null) {
                return ResultUtil.error(9999,"系统繁忙，请刷新页面后再试！");
            }
            if (one.getState()!=0) {
                return ResultUtil.error(9999, one.getZhifubaoName() + "转账失败！原因是用户已转账");
            }
            if(one.getClassify()==null || one.getClassify()==1){
                return cashAliPay(one);
            }else{
                return cashWxPay(one);
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.error("转账异常："+e.getMessage(),e);
        }finally {
            reentrantReadWriteLock.writeLock().unlock();
        }
        return ResultUtil.error(9999,"系统繁忙，请刷新页面后再试！");
    }

    public Result cashAliPay(CashOut one){
        //获取全局名称
        //是否开启企业支付
        CommonInfo commonInfo = commonRepository.findOne(87);
        if(StringUtils.isEmpty(one.getOrderNumber())){
            one.setOrderNumber(String.valueOf(System.currentTimeMillis()));
        }
        DecimalFormat df= new DecimalFormat("#.00");
        Double money=Double.parseDouble(one.getMoney());
        one.setMoney(df.format(money));
        if (commonInfo.getValue() != null && commonInfo.getValue().equals("1")) {
            val aliPayWithdrawModel = AliPayWithdrawModel.builder()
                    .out_biz_no(one.getOrderNumber())
                    .amount(new BigDecimal(one.getMoney()))
                    .payee_account(one.getZhifubao())
                    .payee_real_name(one.getZhifubaoName())
                    .payee_type(AliPayConstants.PAY_TYPE)
                    .remark(commonRepository.findOne(12).getValue() + "佣金结算")
                    .build();
            String json = JSON.toJSONString(aliPayWithdrawModel);
            //实例化连接对象
            AlipayFundTransToaccountTransferRequest withdrawRequest = new AlipayFundTransToaccountTransferRequest();
            withdrawRequest.setBizContent(json);
            AlipayClient alipayClient = new DefaultAlipayClient(AliPayConstants.REQUEST_URL,
                    commonRepository.findOne(63).getValue(), commonRepository.findOne(65).getValue(), AliPayConstants.FORMAT,
                    AliPayConstants.CHARSET, commonRepository.findOne(64).getValue(), AliPayConstants.SIGNTYPE);
            try {
                AlipayFundTransToaccountTransferResponse response = alipayClient.execute(withdrawRequest);
                if (AliPayConstants.SUCCESS_CODE.equalsIgnoreCase(response.getCode())) {
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    one.setState(1);
                    one.setOut(true);
                    one.setOutAt(sdf.format(new Date()));
                    CashOut save = cashJpaRepository.save(one);
                    UserInfo userInfo = userJpaRepository.getOne(Long.valueOf(save.getUserId()));
                    if (userInfo != null && userInfo.getOpenId() != null) {
                        //提现通知消息
                        cashOutSuccess(userInfo.getOpenId(), save.getOutAt(), save.getMoney(), save.getZhifubao(), commonRepository.findOne(19).getValue());
                    }
                    return ResultUtil.success(one.getZhifubaoName() + "转账成功");
                } else {
                    return ResultUtil.error(9999, one.getZhifubaoName() + "转账失败！" + response.getSubMsg());
                }
            } catch (AlipayApiException e) {
                logger.error("零钱提现异常原因:" + e.getMessage());
                e.printStackTrace();
                return ResultUtil.error(9999, one.getZhifubaoName() + "转账失败！" + e.getMessage());

            }
        }else if(commonInfo.getValue() != null && commonInfo.getValue().equals("2")){
            String url="https://api.pay.yungouos.com/api/finance/repay/alipay";
            Map<String,String> map=new HashMap<>();
            CommonInfo merchantId = commonRepository.findOne(235);
            CommonInfo password = commonRepository.findOne(236);
            map.put("merchant_id",merchantId.getValue());//YunGouOS商户ID。登录YunGouOS.com-》账户设置-》开发者身份-》账户商户号；
            map.put("out_trade_no",one.getOrderNumber());
            map.put("account",one.getZhifubao());
            map.put("account_name",one.getZhifubaoName());
            map.put("money",one.getMoney());
            map.put("desc",commonRepository.findOne(12).getValue() + "佣金结算");
            Map<String,Object> maps=new HashMap<>();
            maps.put("merchant_id",merchantId.getValue());
            maps.put("out_trade_no",one.getOrderNumber());
            maps.put("account",one.getZhifubao());
            maps.put("account_name",one.getZhifubaoName());
            maps.put("money",one.getMoney());
            maps.put("desc",commonRepository.findOne(12).getValue() + "佣金结算");
            map.put("sign", PaySignUtil.createSign(maps,password.getValue()));
            String s = HttpClientUtil.doPost(url, map);
            JSONObject jsonObject = JSON.parseObject(s);
            String code = jsonObject.getString("code");
            if("1".equals(code)){
                JSONObject data = jsonObject.getJSONObject("data");
                String status = data.getString("status");
                if("1".equals(status)){
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    one.setState(1);
                    one.setOutAt(sdf.format(new Date()));
                    CashOut save = cashJpaRepository.save(one);
                    return ResultUtil.success(one.getZhifubaoName() + "转账成功");
                }else{
                    return ResultUtil.error(9999,"转账失败，原因："+data.getString("reason"));
                }
            }else{
                logger.error("yungouos:"+s);
                return ResultUtil.error(9999,"转账失败，参数配置有误！");
            }
        }else if (commonInfo.getValue() != null && commonInfo.getValue().equals("3")) {
            try {
                CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
                certAlipayRequest.setServerUrl("https://openapi.alipay.com/gateway.do");  //gateway:支付宝网关（固定）https://openapi.alipay.com/gateway.do
                certAlipayRequest.setAppId(commonRepository.findOne(170).getValue());  //APPID 即创建应用后生成,详情见创建应用并获取 APPID
                certAlipayRequest.setPrivateKey(commonRepository.findOne(171).getValue());  //开发者应用私钥，由开发者自己生成
                certAlipayRequest.setFormat("json");  //参数返回格式，只支持 json 格式
                certAlipayRequest.setCharset(AliPayConstants.CHARSET);  //请求和签名使用的字符编码格式，支持 GBK和 UTF-8
                certAlipayRequest.setSignType(AliPayConstants.SIGNTYPE);  //商户生成签名字符串所使用的签名算法类型，目前支持 RSA2 和 RSA，推荐商家使用 RSA2。

                CommonInfo url = commonRepository.findOne(200);
                certAlipayRequest.setCertPath(url.getValue()+"/appCertPublicKey.crt"); //应用公钥证书路径（app_cert_path 文件绝对路径）
                certAlipayRequest.setAlipayPublicCertPath(url.getValue()+"/alipayCertPublicKey_RSA2.crt"); //支付宝公钥证书文件路径（alipay_cert_path 文件绝对路径）
                certAlipayRequest.setRootCertPath(url.getValue()+"/alipayRootCert.crt");  //支付宝CA根证书文件路径（alipay_root_cert_path 文件绝对路径）
                AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
                AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
                request.setBizContent("{" +
                        "\"out_biz_no\":\""+one.getOrderNumber()+"\"," +
                        "\"trans_amount\":"+new BigDecimal(one.getMoney())+"," +
                        "\"product_code\":\"TRANS_ACCOUNT_NO_PWD\"," +
                        "\"biz_scene\":\"DIRECT_TRANSFER\"," +
                        "\"order_title\":\""+commonRepository.findOne(12).getValue() + "佣金结算"+"\"," +
                        "\"payee_info\":{" +
                        "\"identity\":\""+one.getZhifubao()+"\"," +
                        "\"identity_type\":\"ALIPAY_LOGON_ID\"," +
                        "\"name\":\""+one.getZhifubaoName()+"\"," +
                        "}," +
                        "\"remark\":\""+commonRepository.findOne(12).getValue() + "佣金结算"+"\"" +
                        "}");
                AlipayFundTransUniTransferResponse response = null;
                response = alipayClient.certificateExecute(request);
                if(response.isSuccess()){
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    one.setState(1);
                    one.setOut(true);
                    one.setOutAt(sdf.format(new Date()));
                    CashOut save = cashJpaRepository.save(one);
                    UserInfo userInfo = userJpaRepository.findById(Long.valueOf(save.getUserId())).orElse(null);
                    if (userInfo != null && userInfo.getOpenId() != null) {
                        //提现通知消息
                        cashOutSuccess(userInfo.getOpenId(), save.getOutAt(), save.getMoney(), save.getZhifubao(), commonRepository.findOne(19).getValue());
                    }
                    return ResultUtil.success(one.getZhifubaoName() + "转账成功");
                } else {
                    return ResultUtil.error(9999, one.getZhifubaoName() + "转账失败！" + response.getSubMsg());
                }
            } catch (AlipayApiException e) {
                logger.error("零钱提现异常原因:" + e.getMessage());
                e.printStackTrace();
                return ResultUtil.error(9999, one.getZhifubaoName() + "转账失败！" + e.getMessage());
            }
        } else {
            //人工转账后改变状态的
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date now = new Date();
            one.setState(1);
            one.setOut(true);
            one.setOutAt(sdf.format(now));
            CashOut save = cashJpaRepository.save(one);
            String userId = save.getUserId();
            UserInfo userInfo = userJpaRepository.findById(Long.valueOf(userId)).orElse(null);
            if (userInfo != null && userInfo.getOpenId() != null) {
                //推送提现通知消息
                cashOutSuccess(userInfo.getOpenId(), save.getOutAt(), save.getMoney(), save.getZhifubao(), commonRepository.findOne(19).getValue());
            }
            return ResultUtil.success(one.getZhifubaoName() + "转账成功");
        }
    }


    private Result cashWxPay(CashOut one){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        UserInfo userEntity = userRepository.getUserById(Long.parseLong(one.getUserId()));
        if(org.apache.commons.lang.StringUtils.isEmpty(one.getOrderNumber())){
            one.setOrderNumber(String.valueOf(System.currentTimeMillis()));
        }
        String value = commonRepository.findOne(244).getValue();
        if("1".equals(value)){
            WxPay wxPay=new WxPay();
            CommonInfo mchId = commonRepository.findOne(76);
            CommonInfo key = commonRepository.findOne(75);
            //小程序或公众号appid
            if(one.getClassify()==2){
                CommonInfo mchAppId = commonRepository.findOne(45);
                wxPay.setMch_appid(mchAppId.getValue());
                wxPay.setOpenid(userEntity.getMpId());
            }else if(one.getClassify()==3){
                CommonInfo mchAppId = commonRepository.findOne(5);
                wxPay.setMch_appid(mchAppId.getValue());
                wxPay.setOpenid(userEntity.getOpenId());
            }else if(one.getClassify()==4){
                CommonInfo mchAppId = commonRepository.findOne(74);
                wxPay.setMch_appid(mchAppId.getValue());
                wxPay.setOpenid(userEntity.getOpen_uid());
            }
//        else{
//            CommonInfo mchAppId = commonInfoService.findOne(74);
//            wxPay.setMch_appid(mchAppId.getValue());
//            wxPay.setOpenid(userEntity.get());
//        }
            //商户号id
            wxPay.setMchid(mchId.getValue());
            //随机字符
            wxPay.setNonce_str(WxPayUtils.generateNonceStr());
            //商户订单号  需保持唯一
            wxPay.setPartner_trade_no(one.getOrderNumber());
            //用户openId

            //NO_CHECK：不校验真实姓名
            //FORCE_CHECK：强校验真实姓名
            wxPay.setCheck_name("NO_CHECK");
            //转账金额 微信为分
            double v = Double.parseDouble(one.getMoney());
            Double mul = AmountCalUtils.mul(v, 100);
            Integer amount=mul.intValue();
            wxPay.setAmount(amount);
            //备注
            CommonInfo one1 = commonRepository.findOne(12);
            wxPay.setDesc(one1.getValue()+"提现金额到账");
            wxPay.setSign(WxPayUtils.createSign(BeanUtil.beanToMap(wxPay), key.getValue()));


            String xmlParam = XmlUtil.beanToXml(wxPay,WxPay.class);
            WeChatPayRequest weChatPayRequest = new WeChatPayRequest();

            String returnXml = null;
            try {
                CommonInfo zsUlr = commonRepository.findOne(245);
                returnXml = weChatPayRequest.request(zsUlr.getValue(),WxPayUtils.WX_COM_DO_TRANS_URL,xmlParam,true,mchId.getValue());
                WxResult wxResult = XmlUtil.xmlToBean(returnXml, WxResult.class);
                if(wxResult.getReturn_code().equals("SUCCESS")){
                    if(one.getOrderNumber().equals(wxResult.getPartner_trade_no())){
                        one.setState(1);
                        one.setOut(true);
                        one.setOutAt(sdf.format(new Date()));
                        CashOut save = cashJpaRepository.save(one);
                        UserInfo userInfo = userJpaRepository.findById(Long.valueOf(save.getUserId())).orElse(null);
                        if (userInfo != null && userInfo.getOpenId() != null) {
                            //提现通知消息
                            cashOutSuccess(userInfo.getOpenId(), save.getOutAt(), save.getMoney(), save.getZhifubao(), commonRepository.findOne(19).getValue());
                        }
                        return ResultUtil.success(one.getZhifubaoName() + "转账成功");
                    }else{
                        return ResultUtil.error(9999,"转账失败！原因："+wxResult.getErr_code_des());
                    }
                }else{
                    return ResultUtil.error(9999,"转账失败！状态码："+wxResult.getErr_code_des());
                }
            } catch (Exception e) {
                logger.error("转账异常："+e.getMessage(),e);
                logger.error("postWxTransfers 微信处理异常 ==>{}", ExceptionUtils.getStackTrace(e));
            }
        }else{
            Date now = new Date();
            one.setState(1);
            one.setOut(true);
            one.setOutAt(sdf.format(now));
            CashOut save = cashJpaRepository.save(one);
            String userId = save.getUserId();
            UserInfo userInfo = userJpaRepository.findById(Long.valueOf(userId)).orElse(null);
            if (userInfo!=null && userInfo.getOpenId() != null) {
                //推送提现通知消息
                cashOutSuccess(userInfo.getOpenId(), save.getOutAt(), save.getMoney(), save.getZhifubao(), commonRepository.findOne(19).getValue());
            }
        }
        return ResultUtil.error(9999,"转账失败！");
    }


    @RequestMapping(value = "/v1/refund/{cashId}/{content}", method = RequestMethod.POST)
    @ApiOperation("管理平台退款")
    @ResponseBody
    public Result refund(@PathVariable("cashId") Long cashId,@PathVariable("content") String content) {
        CashOut one = cashJpaRepository.findById(cashId).orElse(null);
        if (one == null) {
            return ResultUtil.error(ExceptionEnum.USER_NOT_FIND);
        }
        if(one.getState()!=0){
            return ResultUtil.error(-100,"已经转账或退款!");
        }
        String date = String.valueOf(System.currentTimeMillis());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date now = new Date();
        one.setState(-1);
        one.setRefund(content);
        one.setOutAt(sdf.format(now));
        CashOut save = cashJpaRepository.save(one);
        String moneys=save.getMoney();
        if(save.getRate()!=null){
            Double rate = save.getRate();
            double add = AmountCalUtils.add(Double.parseDouble(moneys), rate);
            moneys=String.valueOf(add);
        }
        String userId = save.getUserId();
        UserInfo userInfo = userJpaRepository.getOne(Long.valueOf(userId));
        if(userInfo!=null){
            //将金额退还
            userRepository.updateJiFenAdd(moneys,Long.parseLong(save.getUserId()));
            iMoneyDetailsService.saveBody(userInfo.getId(), 1, 4, sdf.format(now) + "退款提醒", content, Double.parseDouble(moneys));
            if (userInfo.getOpenId() != null) {
                //推送提现通知消息
                refundSuccess(userInfo.getOpenId(), save.getOutAt(), moneys,  commonRepository.findOne(19).getValue(),content);
            }
        }
        return ResultUtil.success();
    }


    /**
     * 瞄有券第三方转账
     *
     * @param alipay   支付宝账号
     * @param realname 真实姓名
     * @param money    支付金额
     * @param beizhu   备注
     */
    private void sendMoney(String alipay, String realname, String money, String beizhu) {
        CommonInfo three = commonRepository.findOne(30);
        String apkey = Config.MIAOYOUQUN_Key;
        if (three != null) {
            apkey = three.getValue();
        }
        long l = System.currentTimeMillis();
        String url = Config.MIAOYOUQUN_URL + "/platform/paymentToAlipay?apkey=" + apkey + "&thirdorder=" + l + "&beizhu=" + beizhu + "&realname=" + realname + "&money=" + money + "&alipay=" + alipay;
        String s = HttpClient.doGet(url);
    }

    /**
     * 查询某个用户的提现记录
     *
     * @param relationId
     * @return
     */
    @RequestMapping(value = "/list/{relationId}", method = RequestMethod.GET)
    @ApiOperation("用户端查询某个用户的提现记录")
    @ResponseBody
    public Result findOne(@PathVariable String relationId) {
        return iCashService.findOne(relationId);
    }


    /**
     * 查询某个用户的提现记录
     *
     * @param
     * @return
     */
    @RequestMapping(value = "/selectCashOutList/{id}", method = RequestMethod.GET)
    @ApiOperation("用户端查询某个用户的提现记录")
    @ResponseBody
    public Result selectCashOutList(HttpServletRequest request,@PathVariable String id) {
        Object userIds = request.getAttribute("userId");
        if(userIds!=null){
            id=String.valueOf(userIds);
        }else{
            Object adminId = request.getAttribute("adminId");
            if(adminId==null){
                return ResultUtil.success();
            }
        }
        return iCashService.selectCashOutList(id);
    }



    /**
     * 前端获取已经提现了多少钱
     *
     * @param relationId
     * @return
     */
    @RequestMapping(value = "/countByRelationId/{relationId}", method = RequestMethod.GET)
    @ApiOperation("用户端获取已经提现了多少钱")
    @ResponseBody
    public Result countByRelationId(@PathVariable String relationId) {
        return ResultUtil.success(cashRepository.countByRelationId(relationId));
    }

    @RequestMapping(value = "/countByUserId/{id}", method = RequestMethod.GET)
    @ApiOperation("用户端获取已经提现了多少钱")
    @ResponseBody
    public Result countByUserId(HttpServletRequest request,@PathVariable String id) {
        Object userIds = request.getAttribute("userId");
        if(userIds!=null){
            id=String.valueOf(userIds);
        }else{
            Object adminId = request.getAttribute("adminId");
            if(adminId==null){
                return ResultUtil.success();
            }
        }
        return ResultUtil.success(cashRepository.countByUserId(id));
    }

    /**
     * 前端获取用户可以提现的金额
     *
     * @param userId
     * @return
     */
    @RequestMapping(value = "/money/{userId}", method = RequestMethod.GET)
    @ApiOperation("用户端获取用户可以提现的金额")
    @ResponseBody
    public Result cashOutMoney(HttpServletRequest request, @PathVariable Long userId) {
        Object userIds = request.getAttribute("userId");
        if(userIds!=null){
            userId=Long.parseLong(String.valueOf(userIds));
        }else{
            Object adminId = request.getAttribute("adminId");
            if(adminId==null){
                return ResultUtil.success();
            }
        }
        UserInfo one = userJpaRepository.findById(userId).orElse(null);
        if (one != null) {
            UserMoney userMoney = userMoneyService.selectByUserId(one.getId());
            BigDecimal add = new BigDecimal(one.getJifen()).add(BigDecimal.valueOf(userMoney.getMoney()));
            add=add.add(BigDecimal.valueOf(userMoney.getCannotMoney()));
            return ResultUtil.success(add);
        }
        return ResultUtil.error(ExceptionEnum.USER_NOT_FIND);
    }

    /**
     * 用户的信息查询
     *
     * @param userId
     * @return
     */
    @RequestMapping(value = "/userinfo/{userId}", method = RequestMethod.GET)
    @ApiOperation("用户端用户的信息查询")
    @ResponseBody
    public Result cashUserInfo(HttpServletRequest request,@PathVariable Long userId) {
        Object userIds = request.getAttribute("userId");
        if(userIds!=null){
            userId=Long.parseLong(String.valueOf(userIds));
        }else{
            Object adminId = request.getAttribute("adminId");
            if(adminId==null){
                return ResultUtil.success();
            }
        }
        UserInfo one = userJpaRepository.findById(userId).orElse(null);
        if (one != null) {
            return ResultUtil.success(one);
        }
        return ResultUtil.error(ExceptionEnum.USER_NOT_FIND);
    }

    /**
     * 前端修改支付宝账号
     *
     * @param userId
     * @param zhifubao
     * @param zhifubaoName
     * @return
     */
    @RequestMapping(value = "/userinfo", method = RequestMethod.POST)
    @ApiOperation("用户端修改支付宝账号")
    @ResponseBody
    public Result updateZhiFuBao(@RequestParam Long userId, @RequestParam String zhifubao, @RequestParam String zhifubaoName) {
        UserInfo one = userJpaRepository.findById(userId).orElse(null);
        if (one != null) {
            one.setZhifubao(zhifubao);
            one.setZhifubaoName(zhifubaoName);
            UserInfo save = userJpaRepository.save(one);
            return ResultUtil.success(save);
        }
        return ResultUtil.error(ExceptionEnum.USER_NOT_FIND);
    }

    /**
     * 用户发起提现
     *
     * @param userId
     * @return
     */
    @RequestMapping(value = "/out/{userId}", method = RequestMethod.GET)
    @ApiOperation("用户端用户发起提现")
    @ResponseBody
    public Result cashOut(@PathVariable Long userId) {
        UserInfo one = userJpaRepository.findById(userId).orElse(null);
        CommonInfo url = commonRepository.findOne(19);
        if (one != null) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date now = new Date();
            if (one.getJifen() != null) {

                CashOut cashOut = new CashOut();
                cashOut.setOut(false);
                cashOut.setZhifubao(one.getZhifubao());
                cashOut.setZhifubaoName(one.getZhifubaoName());
                cashOut.setRelationId(one.getRelationId());
                DecimalFormat df= new DecimalFormat("#.00");
                Double money=Double.parseDouble(one.getJifen());
                cashOut.setMoney(df.format(money));
                cashOut.setCreateAt(sdf.format(now));
                cashOut.setUserId(String.valueOf(one.getId()));
                cashOut.setState(0);
                String date = String.valueOf(System.currentTimeMillis());
                cashOut.setOrderNumber(date);
                CashOut save = cashJpaRepository.save(cashOut);
                one.setJifen("0");
                //推送提现发起消息
                if (one.getOpenId() != null) {
                    cashOut(one.getOpenId(), one.getNickName(), save.getCreateAt(), save.getMoney(), save.getZhifubao(), url.getValue());
                }
                userJpaRepository.save(one);
                iMoneyDetailsService.saveBody(one.getId(),2,4,"用户提现","发起提现，提现金额：-"+save.getMoney(),Double.parseDouble(save.getMoney()));
                return ResultUtil.success(save);
            }
        }
        return ResultUtil.error(ExceptionEnum.USER_NOT_FIND);
    }


    /**
     * 用户发起提现
     *
     * @param userId
     * @return
     */
    @RequestMapping(value = "/v1/out/{userId}/{money}", method = RequestMethod.GET)
    @ApiOperation("用户端用户发起提现")
    @ResponseBody
    public Result cashOutVTwo(@PathVariable("userId") Long userId,@PathVariable("money") Double money) {
        int i = String.valueOf(money).indexOf(".");
        if(money%Integer.parseInt(String.valueOf(money).substring(0, i))!=0){
            return ResultUtil.error(-1,"请重新输入数字，提现金额必须为整数！");
        }
        UserInfo one = userJpaRepository.findById(userId).orElse(null);
        CommonInfo url = commonRepository.findOne(19);
        if (one != null) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date now = new Date();
            //最低提现标准
            CommonInfo one1 = commonRepository.findOne(85);
            double zuiDi = Double.parseDouble(one1.getValue());
            if(money<zuiDi){
                return ResultUtil.error(-1,"金额不满足最低提现要求，请重新输入！");
            }
            double myMoney = Double.parseDouble(one.getJifen());

            //提现手续费
            CommonInfo one2 = commonRepository.findOne(107);
            double rate = Double.parseDouble(one2.getValue());
            //手续费
            Double aDouble = AmountCalUtils.moneyMul(money, rate);
            UserMoney userMoney = userMoneyService.selectByUserId(userId);
            double myMoneys = AmountCalUtils.add(myMoney, userMoney.getMoney());
            if(myMoneys<money){
                return ResultUtil.error(-1,"钱包金额不足，请重新输入！");
            }
            double add = AmountCalUtils.add(aDouble, money);
            DecimalFormat df= new DecimalFormat("#.00");
            String moneys=String.valueOf(money);
            //发起提现  这里要做判断  如果用户钱包金额足够  手续费从钱包中扣除 如果钱包金额不足  则从提现金额中扣除
            if(myMoneys>=add){
                //从钱包中扣除
                //判断jifen字段钱是否足够扣除
                if(myMoney>=add){
                    userRepository.updateJiFenDelete(String.valueOf(add),one.getId());
                    iMoneyDetailsService.saveBody(one.getId(),2,4,"用户提现","发起提现，提现金额：-"+moneys+",扣除手续费："+aDouble,add);
                }else{
                    //jifen字段金额不够扣除  从userMoney中扣除
                    userRepository.updateJiFenDelete(one.getJifen(),one.getId());
                    Double sub = AmountCalUtils.sub(add, Double.parseDouble(one.getJifen()));
                    userMoneyService.updateMoney(2,one.getId(),sub);
                    iMoneyDetailsService.saveBody(one.getId(),2,4,"用户提现","发起提现，提现金额：-"+moneys+",扣除手续费："+aDouble,add);
                }
            }else{
                //金额不足 从提现金额中扣除手续费
                Double sub = AmountCalUtils.sub(money, Double.parseDouble(one.getJifen()));
                //提现金额扣除手续费 为真实提现金额
                Double m = AmountCalUtils.sub(money,aDouble);
                if(sub<=0){
                    userRepository.updateJiFenDelete(String.valueOf(money),one.getId());
                    moneys = String.valueOf(m);
                    iMoneyDetailsService.saveBody(one.getId(),2,4,"用户提现","发起提现，提现金额：-"+moneys+",扣除手续费："+aDouble,money);
                }else{
                    //jifen字段金额不够扣除  从userMoney中扣除
                    userRepository.updateJiFenDelete(one.getJifen(),one.getId());
                    userMoneyService.updateMoney(2,one.getId(),sub);
                    moneys = String.valueOf(m);
                    iMoneyDetailsService.saveBody(one.getId(),2,4,"用户提现","发起提现，提现金额：-"+moneys+",扣除手续费："+aDouble,money);
                }
            }
            CashOut cashOut = new CashOut();
            cashOut.setOut(false);
            cashOut.setZhifubao(one.getZhifubao());
            cashOut.setZhifubaoName(one.getZhifubaoName());
            cashOut.setRelationId(one.getRelationId());
            cashOut.setMoney(moneys);
            cashOut.setCreateAt(sdf.format(now));
            cashOut.setUserId(String.valueOf(one.getId()));
            cashOut.setState(0);
            cashOut.setRate(aDouble);
            String date = String.valueOf(System.currentTimeMillis());
            cashOut.setOrderNumber(date);
            CashOut save = cashJpaRepository.save(cashOut);
            //推送提现发起消息
            if (one.getOpenId() != null) {
                cashOut(one.getOpenId(), one.getNickName(), save.getCreateAt(), save.getMoney(), save.getZhifubao(), url.getValue());
            }
            return ResultUtil.success(save);
        }

        return ResultUtil.error(ExceptionEnum.USER_NOT_FIND);
    }


    /**
     * 用户发起提现
     *
     * @param userId
     * @return
     */
    @RequestMapping(value = "/v2/out/{userId}/{money}", method = RequestMethod.GET)
    @ApiOperation("用户端用户发起提现")
    @ResponseBody
    public Result cashOutV2(@PathVariable("userId") Long userId,@PathVariable("money") Double money,Integer classify) {
        int i = String.valueOf(money).indexOf(".");
        if(money%Integer.parseInt(String.valueOf(money).substring(0, i))!=0){
            return ResultUtil.error(-1,"请重新输入数字，提现金额必须为整数！");
        }
        UserInfo one = userJpaRepository.findById(userId).orElse(null);
        CommonInfo url = commonRepository.findOne(19);
        if (one != null) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date now = new Date();

            if(classify==2 || classify==3){
                String value = commonRepository.findOne(244).getValue();
                if("2".equals(value)){
                    if(org.apache.commons.lang.StringUtils.isEmpty(one.getWxImg())){
                        return ResultUtil.error(-200,"请绑定微信提现收款码！");
                    }
                }

            }

            //最低提现标准
            CommonInfo one1 = commonRepository.findOne(85);
            double zuiDi = Double.parseDouble(one1.getValue());
            if(money<zuiDi){
                return ResultUtil.error(-1,"金额不满足最低提现要求，请重新输入！");
            }
            double myMoney = Double.parseDouble(one.getJifen());

            //提现手续费
            CommonInfo one2 = commonRepository.findOne(107);
            double rate = Double.parseDouble(one2.getValue());
            //手续费
            Double aDouble = AmountCalUtils.moneyMul(money, rate);
            UserMoney userMoney = userMoneyService.selectByUserId(userId);
            double myMoneys = AmountCalUtils.add(myMoney, userMoney.getMoney());
            if(myMoneys<money){
                return ResultUtil.error(-1,"钱包金额不足，请重新输入！");
            }
            double add = AmountCalUtils.add(aDouble, money);
            DecimalFormat df= new DecimalFormat("#.00");
            String moneys=String.valueOf(money);
            //发起提现  这里要做判断  如果用户钱包金额足够  手续费从钱包中扣除 如果钱包金额不足  则从提现金额中扣除
            if(myMoneys>=add){
                //从钱包中扣除
                //判断jifen字段钱是否足够扣除
                if(myMoney>=add){
                    userRepository.updateJiFenDelete(String.valueOf(add),one.getId());
                    iMoneyDetailsService.saveBody(one.getId(),2,4,"用户提现","发起提现，提现金额：-"+moneys+",扣除手续费："+aDouble,add);
                }else{
                    //jifen字段金额不够扣除  从userMoney中扣除
                    userRepository.updateJiFenDelete(one.getJifen(),one.getId());
                    Double sub = AmountCalUtils.sub(add, Double.parseDouble(one.getJifen()));
                    userMoneyService.updateMoney(2,one.getId(),sub);
                    iMoneyDetailsService.saveBody(one.getId(),2,4,"用户提现","发起提现，提现金额：-"+moneys+",扣除手续费："+aDouble,add);
                }
            }else{
                //金额不足 从提现金额中扣除手续费
                Double sub = AmountCalUtils.sub(money, Double.parseDouble(one.getJifen()));
                //提现金额扣除手续费 为真实提现金额
                Double m = AmountCalUtils.sub(money,aDouble);
                if(sub<=0){
                    userRepository.updateJiFenDelete(String.valueOf(money),one.getId());
                    moneys = String.valueOf(m);
                    iMoneyDetailsService.saveBody(one.getId(),2,4,"用户提现","发起提现，提现金额：-"+moneys+",扣除手续费："+aDouble,money);
                }else{
                    //jifen字段金额不够扣除  从userMoney中扣除
                    userRepository.updateJiFenDelete(one.getJifen(),one.getId());
                    userMoneyService.updateMoney(2,one.getId(),sub);
                    moneys = String.valueOf(m);
                    iMoneyDetailsService.saveBody(one.getId(),2,4,"用户提现","发起提现，提现金额：-"+moneys+",扣除手续费："+aDouble,money);
                }
            }
            CashOut cashOut = new CashOut();
            cashOut.setOut(false);
            cashOut.setZhifubao(one.getZhifubao());
            cashOut.setZhifubaoName(one.getZhifubaoName());
            cashOut.setRelationId(one.getRelationId());
            cashOut.setMoney(moneys);
            cashOut.setCreateAt(sdf.format(now));
            cashOut.setUserId(String.valueOf(one.getId()));
            cashOut.setState(0);
            cashOut.setClassify(classify);
            cashOut.setRate(aDouble);
            String date = String.valueOf(System.currentTimeMillis());
            cashOut.setOrderNumber(date);
            cashOut.setWxImg(one.getWxImg());
            CashOut save = cashJpaRepository.save(cashOut);
            //推送提现发起消息
            if (one.getOpenId() != null) {
                cashOut(one.getOpenId(), one.getNickName(), save.getCreateAt(), save.getMoney(), save.getZhifubao(), url.getValue());
            }
            return ResultUtil.success(save);
        }

        return ResultUtil.error(ExceptionEnum.USER_NOT_FIND);
    }



    /**
     * 申请提现成功通知
     *
     * @param openId
     * @param name
     * @param date
     * @param money
     * @param payWay
     * @param url
     */
    private void cashOut(String openId, String name, String date, String money, String payWay, String url) {
        UserInfo userByWxId = userRepository.getUserByWxId(openId);
        MessageInfo messageInfo = new MessageInfo();
        messageInfo.setState(String.valueOf(5));
        messageInfo.setContent("您好，您的提现申请成功，预计三个工作日到账！提现金额" + money + " 元！支付宝收款账号 " + payWay);
        messageInfo.setTitle("提现通知");
        messageInfo.setUserName(userByWxId.getNickName());
        messageInfo.setUserId(String.valueOf(userByWxId.getId()));
        iMessageService.saveBody(messageInfo);

        //提现通知管理员openid
        CommonInfo one = commonRepository.findOne(18);
        //后台管理平台域名配置
        CommonInfo two = commonRepository.findOne(20);

        CommonInfo three = commonRepository.findOne(39);
        String apkey = Config.CashNotification;
        if (three != null) {
            apkey = three.getValue();
        }
        if (userByWxId.getClientid() != null) {
            userService.pushToSingle("提现通知", "您好，您的提现申请成功，预计三个工作日到账！提现金额" + money + " 元！支付宝收款账号 " + payWay, userByWxId.getClientid());
        }
        LinkedHashMap<String, TemplateMessageItem> data = new LinkedHashMap<>();
        data.put("amount6", new TemplateMessageItem(money, "#d71345"));
        data.put("thing4", new TemplateMessageItem("发起提现", "#d71345"));
        data.put("time8", new TemplateMessageItem(date, "#d71345"));
        accountService.sendWxMessage(apkey, data, openId, url);

        /*LinkedHashMap<String, TemplateMessageItem> data1 = new LinkedHashMap<>();
        data1.put("first", new TemplateMessageItem("收到一个提现申请！ 请尽快处理！", "#d71345"));
        data1.put("keyword1", new TemplateMessageItem(name, "#d71345"));
        data1.put("keyword2", new TemplateMessageItem(date, "#d71345"));
        data1.put("keyword3", new TemplateMessageItem(money + " 元", "#d71345"));
        data1.put("keyword4", new TemplateMessageItem("支付宝收款账号 " + payWay, "#d71345"));
        data1.put("remark", new TemplateMessageItem("感谢您的使用！如有疑问请在公众号中发送您的问题联系客服", null));
        accountService.sendWxMessage(apkey, data1, one.getValue() != null ? one.getValue() : Config.CashOpenId, two.getValue() != null ? two.getValue() : Config.CashAdmin);
*/
    }

    /**
     * 退款成功通知
     *
     * @param openId
     * @param date
     * @param money
     * @param url
     */
    private void refundSuccess(String openId, String date, String money, String url,String content) {
        UserInfo userByWxId = userRepository.getUserByWxId(openId);
        MessageInfo messageInfo = new MessageInfo();
        messageInfo.setState(String.valueOf(5));
        messageInfo.setContent(content);
        messageInfo.setTitle("提现失败提醒");
        messageInfo.setUserName(userByWxId.getNickName());
        messageInfo.setUserId(String.valueOf(userByWxId.getId()));
        iMessageService.saveBody(messageInfo);
        if (userByWxId.getClientid() != null) {
            userService.pushToSingle("提现失败提醒", content, userByWxId.getClientid());
        }
        CommonInfo three = commonRepository.findOne(39);
        String apkey = Config.TiXianSuccessNotification;
        if (three != null) {
            apkey = three.getValue();
        }
        LinkedHashMap<String, TemplateMessageItem> data = new LinkedHashMap<>();
        data.put("amount6", new TemplateMessageItem(money, "#d71345"));
        data.put("thing4", new TemplateMessageItem("提现失败", "#d71345"));
        data.put("time8", new TemplateMessageItem(date, "#d71345"));
        accountService.sendWxMessage(apkey, data, openId, url);
    }


    /**
     * 提现成功通知
     *
     * @param openId
     * @param date
     * @param money
     * @param payWay
     * @param url
     */
    private void cashOutSuccess(String openId, String date, String money, String payWay, String url) {
        UserInfo userByWxId = userRepository.getUserByWxId(openId);
        MessageInfo messageInfo = new MessageInfo();
        messageInfo.setState(String.valueOf(5));
        messageInfo.setContent("您好，您的提现转账成功，请注意查收！提现金额【" + money + "元】！支付宝收款账号 " + payWay + "感谢您的使用！如有疑问请在公众号中发送您的问题联系客服");
        messageInfo.setTitle("提现成功通知");
        messageInfo.setUserName(userByWxId.getNickName());
        messageInfo.setUserId(String.valueOf(userByWxId.getId()));
        iMessageService.saveBody(messageInfo);
        if (userByWxId.getClientid() != null) {
            userService.pushToSingle("提现成功通知", "您好，您的提现转账成功，请注意查收！提现金额【" + money + "元】！支付宝收款账号 " + payWay + "感谢您的使用！如有疑问请在公众号中发送您的问题联系客服", userByWxId.getClientid());
        }
        CommonInfo three = commonRepository.findOne(39);
        String apkey = Config.TiXianSuccessNotification;
        if (three != null) {
            apkey = three.getValue();
        }
        LinkedHashMap<String, TemplateMessageItem> data = new LinkedHashMap<>();
        data.put("amount6", new TemplateMessageItem(money, "#d71345"));
        data.put("thing4", new TemplateMessageItem("提现成功", "#d71345"));
        data.put("time8", new TemplateMessageItem(date, "#d71345"));
        accountService.sendWxMessage(apkey, data, openId, url);
    }


}
